#ifndef HTTP_h
#define HTTP_h
#include <memory>
#include <iostream>
#include <sstream>
#include <unordered_map>
#include "Tcpserve.hpp"
#include "Util.hpp"
std::string rootpath = "./wwwroot";
class httprequest
{
public:
    httprequest()
    {
    }
    std::string getreqline(std::string &str)
    {
        bool n = Util::ReadOneLine(str, &_reqline, "\n");
        if (n == false)
        {
            LOG(LogLevel::DEBUG) << "获取请求行失败";
            return "";
        }
        return _reqline;
    }
    void Deseralize(std::string &str)
    {
       // LOG(LogLevel::DEBUG) << str;
        getreqline(str);
        parsereqline();
        if (_uri == "/")
        {
            _uri = rootpath + "/index.html";
        }
        else
        {
            _uri = rootpath + _uri;
        }
        LOG(LogLevel::DEBUG) << "method:" << _method;
        LOG(LogLevel::DEBUG) << "uri:" << _uri;
        LOG(LogLevel::DEBUG) << "version:" << _version;
        if (_method == "GET")
        {
            _isstatic = true;
        }
        else
        {
            _isstatic = false;
        }
        // 如果想要拿到请求主题可以继续进行拿到content_type读取字节
    }
    void parsereqline()
    {
        std::istringstream ss(_reqline);
        ss >> _method >> _uri >> _version;
        LOG(LogLevel::DEBUG) << "method:" << _method;
        LOG(LogLevel::DEBUG) << "uri:" << _uri;
        LOG(LogLevel::DEBUG) << "version:" << _version;
    }
    bool isstatic()
    {
        return _isstatic;
    }
    std::string Method()
    {
        return _method;
    }
    std::string URI()
    {
        return _uri;
    }

private:
    std::string _reqline;
    std::string _method;
    std::string _uri;
    std::string _version;

    std::unordered_map<std::string, std::string> _headers;

    std::string _payload; // 有效载荷

    bool _isstatic;
};
class httpresponse
{
public:
    void setheaders(std::string key, std::string value)
    {
        _headers.insert(std::make_pair(key, value));
    }
    void setcode(int code)
    {
        _code = code;
    }
    void setdesc(std::string des)
    {
        _desc = des;
    }

    std::string parse()
    {
        auto pos = _targetfile.rfind(".");
        std::string tem = _targetfile.substr(pos + 1);
        if (tem == "mp3")
        {
            return "audio/mp3";
        }
        else if(tem=="html")
        {
            return "text/html";
        }
        else
        {
            return "";
        }
    }
    void MakeResponse()
    {
        bool n = Util::ReadFileContent(_targetfile, &_payload);
        if (n)
        {
            setcode(200);
            setdesc("ok");
            setheaders("Content-Length", std::to_string(Util::FileSize(_targetfile)));
            setheaders("Content-Type",parse());
            LOG(LogLevel::DEBUG)<<parse();
        }
        else
        {
            setcode(404);
            setdesc("ok");
        }
    }
    std::string Searlize()
    {
        std::string reponline = "HTTP/1.1" + std::string(" ") + std::to_string(_code) + std::string(" ") + _desc + "\r\n";
        std::string head;
        for (auto &ch : _headers)
        {
            head += ch.first + ": " + ch.second + "\r\n";
        }
        _payload = reponline + head + "\r\n" + _payload;
        //LOG(LogLevel::DEBUG) << _payload;
        return _payload;
    }
    void Desearlize(std::string str)
    {
    }
    void settargetfile(std::string file)
    {
        _targetfile = file;
    }

private:
    std::string _version;
    int _code;
    std::string _desc;

    std::unordered_map<std::string, std::string> _headers;

    std::string _payload;

    std::string _targetfile;
};
class Htpp
{
public:
    Htpp(uint16_t port) : _tsvp(std::make_unique<TcpServe>(port))
    {
    }
    void execute(std::shared_ptr<Socket> sockfd, InetAddr peer)
    {
        // 直接读取请求即可
        std::string requststr;
        int n = sockfd->Recive(&requststr);
        httprequest req;
        req.Deseralize(requststr);
        httpresponse reps;
        if (req.isstatic())
        {
            // 静态资源处理
            // 下面构建应答
            reps.settargetfile(req.URI());
            reps.MakeResponse();
            std::string text = reps.Searlize();
            sockfd->Send(text);
        }
        else
        {
            // 动态资源请求
        }
    }
    void Start()
    {
        _tsvp->Start([this](std::shared_ptr<Socket> sockfd, InetAddr peer)
                     { this->execute(sockfd, peer); });
    }
    ~Htpp()
    {
    }

private:
    std::unique_ptr<TcpServe> _tsvp;
};
#endif